python面向对象(三)

类的保留方法的使用。运算符重写,类的属性控制,上下文管理器,迭代器。

动态语言的“鸭子类型”:并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()方法,返回其内容。但是,许多对象,只要有read()方法,都被视为“file-like object“。许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,完全可以传入任何实现了read()方法的对象。

类的运算

  • 运算符的理解

    运算体现一种操作逻辑,广义角度,任何程序都被认为是运算。

    python中运算体现为运算符的重写

    不能重写python语言内置类型的运算符

    不能新建运算符

    is and not or不能被重写

  • 各类运算符的重写

    | 一元算数运算相关的保留方法 | 描述 | 使用 |
    | ————————– | ——– | ——– |
    | __pos__(self) | 取正 | +obj |
    | __neg__(self) | 取负 | -obj |
    | __abs__(self) | 取绝对值 | abs(obj) |
    | __invert__(self) | 取反 | ~obj |

    | 二元算数运算相关的保留方法 | 描述 | 使用 |
    | ————————– | —————- | —————— |
    | __add__(self, other) | 加 | obj + other |
    | __sub__(self, other) | 减 | obj - other |
    | __mul__(self, other) | 乘 | obj * other |
    | __truediv__(self, other) | 除 | obj / other |
    | __floordiv__(self, other) | 整数除(地板除) | obj // other |
    | __mod__(self, other) | 取模 | obj % other |
    | __divmod__(self, other) | 除模 | divmod(obj, other) |
    | __pow__(self, other) | 幂运算 | obj ** other |
    | __lshift__(self, other) | 左移 | obj << other |
    | __rshift__(self, other) | 右移 | obj >> other |
    | __and__(self, other) | 按位与 | obj & other |
    | __xor__(self, other) | 按位异或 | obj ^ other |
    | __or__(self, other) | 按位或 | obj | other |

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 算数运算符重写示例
    class NewList(list):
    def __add__(self, other):
    result = []
    for i in range(len(self)):
    try:
    result.append(self[i] + other[i])
    except:
    result.append(self[i])
    return result


    ls = NewList([1, 2, 3, 4, 5, 6])
    lt = NewList([1, 2, 3, 4])
    print(ls + lt)

    '''输出结果
    [2, 4, 6, 8, 5, 6]
    '''

    | 比较运算符相关的保留方法 | 描述 | 使用 |
    | ———————— | ——– | ———— |
    | __lt__(self, other) | 小于 | obj < other |
    | __le__(self, other) | 小于等于 | obj <= other |
    | __eq__(self, other) | 等于 | obj == other |
    | __ne__(self, other) | 不等于 | obj != other |
    | __gt__(self, other) | 大于 | obj > other |
    | __ge__(self, other) | 大于等于 | obj >= other |

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 比较运算符重写示例
    class NewList(list):
    def __lt__(self, other):
    "以各元素算术和为比较依据"
    s, t = 0, 0
    for c in self:
    s += c
    for c in other:
    t += c
    return s < t


    ls = NewList([6, 1, 2, 3])
    lt = NewList([1, 2, 3, 99])
    print([6, 1, 2, 3] < [1, 2, 3, 99])
    print(ls < lt)

    '''输出结果
    False
    True
    '''

    | 成员运算符相关的保留方法 | 描述 | 使用 |
    | ————————– | —————————– | ————– |
    | __getitem__(self, key) | 获取对象中序号为整数k的元素 | obj[key] |
    | __setitem__(self, key, v) | 为对象中序号为整数k的元素赋值 | obj[key] = v |
    | __delitem__(self, key) | 删除对象中序号为整数k的元素 | del obj[key] |
    | __reversed__(self) | 逆序 | obj.reversed() |
    | __contains__(self, item) | 判断是否in | item in obj |

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 成员运算符重写示例
    class NewList(list):
    def __contains__(self, item ):
    "各元素算术和也作为成员"
    s = 0
    for c in self:
    s += c
    if super().__contains__( item ) or item == s:
    return True
    else :
    return False


    ls = NewList([6,1,2,3])
    print(6 in ls, 12 in ls)
    '''
    True
    True
    '''

    | 其他运算符相关的保留方法 | 描述 | 使用 |
    | —————————— | ———————- | ————————– |
    | __str__(self) | 定义对象转字符串 | str(obj) |
    | __int__(self) | 定义对象转整数 | int(obj) |
    | __float__(self) | 定义对象转浮点数 | float(obj) |
    | __complex__(self) | 定义对象转复数 | complex(obj) |
    | __byets__(self) | 定义对象转字节串 | byets(obj) |
    | __bool__(self) | 定义对象转布尔类型 | bool(obj) |
    | __repr__(self) | 定义对象的可打印字符串 | repr(obj) |
    | __len__(self) | 定义对象长度 | len(obj) |
    | __round__(self, n=None) | 定义对象四舍五入 | round(obj) |
    | __format__(self, format_spec) | 定义对象格式化输出 | obj.format() format(obj) |

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class myStr(object):
    def __init__(self, data):
    self.data = data

    def __repr__(self):
    return ','.join(self.data)


    a = myStr('hello')
    print(repr(a))

    '''输出结果
    h,e,l,l,o
    '''

类的属性控制

设置对象属性

1
2
3
4
5
6
7
8
9
__setattr__(self,name,value) # 一般不需要定义,直接用父类继承的

# 错误的写法,会引起循环递归
def __setattr__(self, name, value):
setattr(self, name,value)

# 正确的写法
def __setattr__(self, name, value):
self.__dict__[name] = value

获取对象属性

1
2
__getattr__(self, name) #属性在默认情况下没有被查询到时,访问这个
__getattribute__(self, naem) # 每次访问对象的属性时,一定会调用。更容易引起无限递归

删除对象属性

1
__delattr__(self, name) # 内建del调用这个

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Programer(object):
def __init__(self, name, age):
self.name = name
self.age = age

def __getattribute__(self, name):
# return getattr(self, name) # 错误的写法
# return self.__dict__[name] # 错误的写法
return super(Programer, self).__getattribute__(name)

def __setattr__(self, name, value):
# setattr(self, name, value) #错误的写法
self.__dict__[name] = value


if __name__ == '__main__':
p = Programer('albert', 25)
print(p.name)

上下文管理器

上下文 Context:程序执行中某个状态

  • 程序执行所需的一些内外部参数,构成了程序运行时状态
  • 上下文是用来表达程序运行状态的概念,对应内存状态
  • 上下文是程序中断保留或恢复运行的重要状态信息

上下文管理器:一个可以在程序中加载独立上下文的对象

  • 万物皆对象:上下文管理器也是一个对象,管理一个独立上下文区域
  • 上下文管理器使用with显式创建
  • 进入和退出分别对应enter()和exit()方法
1
2
3
4
5
6
with 表达式 as 对象引用:
语句块
'''
__enter__()执行开始,返回结果绑定给对象引用。
语句块执行结束,__exit__()执行,退出上下文区域
'''
1
2
3
4
5
6
# 简单例子
# 文件操作打开及管理
wiht open('xxx.txt', 'r') as f:
for line in f:
print(line)
# with 结束后,文件被自动关闭。
1
2
3
4
# with 可以包含多个表达式及as
with open('xxx.txt', 'r') as fi, open('yyy.txt', 'w') as fo:
for line in fi:
fo.write(line)

只要实现了双下划线enter()和exit()方法就可以支持上下文管理器

python支持的对象:

  • file
  • decimal.Context
  • thread.LockType
  • threading.Lock
  • threading.Rlock
  • threading.Condition
  • threading.Semaphore
  • threading.BoundedSemaphore

也可以自定义对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Demo():
def __init__(self, name):
self.name = name

def __enter(self):
print('进入上下文管理器')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('退出上下文管理器')

def run(self):
print('Demo 的一个实例对象正在运行')

with Demo('obj') as d:
# as引用的式__enter__()返回值
d.run()

迭代器

迭代器类型 Iterator Types:实现容器中元素的迭代

  • 容器:Container:包含一组元素的数据类型,如全部组合数据类型
  • 迭代器:容器之上的一种迭代,迭代方式以对象形式表达
  • 迭代器定义了逐一获取容器中元素的方法
  • 迭代器是一个实现了iter()和next()方法的对象,常与for…in…配合使用。

可以配合next(iter)和iter.send()使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class DemoIterator(object):
def __init__(self, container):
self.container = container
self.salt = len(self.container)

def __iter__(self):
return self

def __next__(self):
self.salt -= 1
if self.salt >= 0:
return self.container[self.salt]
else:
raise StopIteration


d = DemoIterator([1, 2, 3, 4, 5, 6])
for i in d:
print(i)
'''
6
5
4
3
2
1
'''

`python

判断一个对象是否是可迭代对象

from collections import Iterable
isinstance(‘abc’, Iterable) # str是否可迭代 True
isinstance([1,2,3], Iterable) # list是否可迭代 True
isinstance(123, Iterable) # 整数是否可迭代 False